{
"ael_seal": "AEL CS Encyclopedia β Β© Ayman Elmasry",
"owner": "Ayman Elmasry",
"legal_entities": [
"Ayman Elmasry LLC (UAE)",
"Ayman Elmasry Advertising & Marketing (Egypt)"
],
"section": "05_Practical_Reverse_Eng (Week 3 Algorithms)",
"syllabus_source": "Harvard CS50x (Practical Reverse Engineering)",
"methodology": "8-Stage Sub-Silicon Execution Paradigm",
"system_version": "v3.0"
}
In this specialized Practical Reverse Engineering wing, we transcend the high-level theoretical definitions of algorithms. Here, we delve into the rigorous architectural mechanics of Big O Complexity by disassembling compiled machine code and analyzing exact Call Stack behavior during searching and sorting operations.
===================================================================================
THE ALGORITHMS INSPECTION ENGINE
===================================================================================
[ Unsorted / Unindexed Memory Structures ]
β
βββΊ Linear Search ββ> O(n) ββ> Sequential Memory Traversal
βββΊ Binary Search ββ> O(log n) ββ> Divide & Conquer Pointer Arithmetic
βββΊ Selection Sort ββ> O(nΒ²) ββ> Quadratic Register Swaps
βββΊ Merge Sort ββ> O(n log n) ββ> Recursive Stack Allocation
===================================================================================
Examining the generated x86_64 Assembly execution paths reveals the stark operational contrast between sequential looping and logarithmic pointer manipulation:
# Linear Search (Loop Traversal)
.L2:
cmpl %esi, (%rdi,%rax,4) # Compare current element with target
je .L5 # Jump if equal (found)
incq %rax # Increment index
cmpq %rdx, %rax # Check loop bound
jne .L2 # Repeat loop
# Binary Search (Pointer Halving)
.L10:
leaq (%rsi,%rdx), %rax # (low + high)
shrq $1, %rax # Divide by 2 (Bitwise Shift Right)
cmpl %ecx, (%rdi,%rax,4) # Compare middle element
...
Merge Sort fundamentally relies on recursive call execution. Inspecting the machine code via objdump demonstrates exactly how runtime stack frames are allocated dynamically to support the divide-and-conquer paradigm:
$ objdump -d mergesort ... 100004a10: 55 pushq %rbp 100004a11: 48 89 e5 movq %rsp, %rbp 100004a14: 48 83 ec 30 subq $48, %rsp # Allocating stack space for sub-arrays ... 100004a3b: e8 d0 ff ff ff callq _mergesort # Recursive call (left half) 100004a48: e8 c3 ff ff ff callq _mergesort # Recursive call (right half) 100004a55: e8 80 01 00 00 callq _merge # Merge subroutine ...
In production-grade engineering, algorithmic execution speed is dictated not solely by asymptotic instruction counts, but heavily by hardware-level memory access patterns across the CPU L1/L2 Cache subsystem.
The Cache Miss Bottleneck: Algorithms exhibiting non-contiguous, random memory leaps trigger expensive CPU cache misses, forcing processor pipeline stalls while fetching cache lines from slow main memory (RAM). Conversely, linear contiguous array traversals fully benefit from hardware prefetching mechanisms.